// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html

import SunCraft from "./SunCraft";
import Craft from "./Craft";
import { AudioManager } from "./GameCore";

const planets = ["europa", "moon", "mercury", "mars", "venus", "earth", "neptune", "uranus", "saturn", "jupiter", "sun", "hole"]

const {ccclass, property} = cc._decorator;

@ccclass
export default class Planet extends cc.Component {

    @property({
        type: cc.Integer,
        tooltip: '星球的id'
    })
    id: number = 0
  
    @property({
        type: cc.SpriteAtlas,
        tooltip: '太阳系星球图集'
    })
    solarSystem: cc.SpriteAtlas = null
  
    @property({
        type: [cc.AudioClip],
        tooltip: '音效列表'
    })
    sounds: cc.AudioClip[] = []
  
    @property({
        type: cc.Prefab,
        tooltip: '合成预制'
    })
    craftPrefab: cc.Prefab = null
  
  
    onLand: boolean = false
    crafted: boolean = false
    sprite: cc.Sprite = null
    manager: SunCraft = null
    alertAction: cc.Tween = null

    init (index, manager = null) {
        this.id = index
        if (manager) this.manager = manager
        this.sprite = this.node.getComponent(cc.Sprite)
        this.sprite.spriteFrame = this.solarSystem.getSpriteFrame(planets[this.id] ? planets[this.id] : 'hole')
    }

    startPhysics() {
        const collider = this.getComponent(cc.PhysicsCircleCollider)
        if (this.crafted) {
            // 如果处于碰撞合成状态，变大
            let scale = collider.radius * 1.2 / this.node.height
            this.node.scale = scale
            cc.tween(this.node)
            .to(0.1, {scale: 0.6}, {easing: "backOut"})
            .call(() => {
                this.crafted = false
            })
            .start()
        } else {
            let body = this.getComponent(cc.RigidBody)
            body.type = cc.RigidBodyType.Dynamic
            collider.sensor = false   
        }
        if (planets[this.id] != 'hole') {
            collider.radius = this.node.height / 2
            collider.apply()
        } else {
            collider.radius = this.node.height / 3 * (this.id) / 11
            collider.apply()
        }
    }

    // 合并时的动画效果
    createCraft() {
        // 播放合并的声音
        AudioManager.playSe(this.sounds[0], 1)
        AudioManager.playSe(this.sounds[1], 1)

        // 展示动画
        let craft = cc.instantiate(this.craftPrefab);
        this.node.addChild(craft);

        const instance = craft.getComponent(Craft)
        instance.showCraft(cc.v2(0, 0), this.node.height)
    }

    onBeginContact(contact: cc.PhysicsContact, selfCollider: cc.PhysicsCircleCollider, otherCollider: cc.PhysicsCollider) {
        if (this.crafted || selfCollider.body.type != cc.RigidBodyType.Dynamic) return 
        if (selfCollider.node && otherCollider.node) {
            const otherPlanet = otherCollider.node.getComponent(Planet)
            if (otherPlanet && !otherPlanet.crafted && this.id === otherPlanet.id && otherCollider.body.type === cc.RigidBodyType.Dynamic) {
                // 碰到相同行星标记
                contact.disabled = true
                this.crafted = true
                otherPlanet.crafted = true
                // 两者在下面的为吸收者
                let absorber = otherCollider.node.y >= this.node.y ? this : otherPlanet
                let otherOne = absorber === this ? otherPlanet : this
                absorber.createCraft()
                // 重设吸收者图片和碰撞箱
                absorber.init(this.id + 1)
                absorber.startPhysics()
                // 设置吞噬另一个星球的效果
                otherOne.getComponent(cc.PhysicsCircleCollider).sensor = true
                otherOne.getComponent(cc.RigidBody).gravityScale = 0
                cc.tween(otherOne.node)
                .to(0.1, {position: this.node.position, scale: 0.2})
                .call((node) => {
                    node.destroy()
                })
                .start()
            } else if (otherCollider.tag != 1) {
                // 碰到地面或者其它无法合成行星
                this.onLand = true
                if (!this.alertAction && otherPlanet && this.node.position.y + selfCollider.radius * this.node.scale > this.manager.line.y) {
                    this.alertAction = 
                    cc.tween(this.node)
                    .repeat(5, 
                        cc.tween().to(0.5, {color: cc.color(255, 128, 128)})
                        .then(cc.tween().to(0.5, {color: cc.color(255, 255, 255)}))
                    )
                    .call((node) => {
                        this.manager.gameOver()
                    })
                    .start()
                }
            }
        }
    }

    
    update (dt) {
        if (this.alertAction) {
            let collider = this.getComponent(cc.PhysicsCircleCollider)
            if (this.node.position.y + collider.radius * this.node.scale <= this.manager.line.y) {
                this.alertAction.stop()
                this.node.color = cc.color(255, 255, 255)
                this.alertAction = null
            }
        }
        
    }
}
